const { ccclass, property, executeInEditMode, menu } = cc._decorator;
const gfx = cc['gfx'];
// import LightningSprite from "./LightningSprite";
class lightningAssembler extends cc.Assembler {

    floatsPerVert = 5;
    vertexesCount = 5;
    indicesCount = 3;

    uvOffset = 2;
    colorOffset = 4;

    public _renderData: cc.RenderData = null;
    public _local: Array<any> = [];
    public vertexes: Array<cc.Vec2> = [];

    get verticesFloats() {
        return this.floatsPerVert * this.vertexesCount;
    }

    init(comp: cc.Sprite) {
        super.init(comp);
        this._renderData = new cc.RenderData();
        this._renderData.init(this);

        this.initLocal();
        this.initData();
    }

    initLocal() {
        this._local = [];
        this._local.length = this.vertexesCount;
    }
    initData() {
        let data = this._renderData;
        // data.createFlexData(0, this.verticesFloats, this.indicesCount, this.getVfmt())
        data.createFlexData(0, this.verticesFloats, this.indicesCount)

        // createFlexData不会填充顶点索引信息，手动补充一下
        // let count = indices.length / this.indicesCount;
        // for (let i = 0, idx = 0; i < count; i++) {
        //     let vertextID = i * 5;
        let idx = 0;
        let vertextID = 0;

        // }
    }
    // getVfmt() {
    //     return vertexFmt;
    // }
    getBuffer() {
        //@ts-ignore
        return cc.renderer._handle._meshBuffer;
    }
    // getBuffer() {
    //     //@ts-ignore
    //     return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
    // }

    updateRenderData(sprite) {
        // if (!sprite._spriteFrame) return;
        // this.packToDynamicAtlas(sprite, sprite._spriteFrame);

        if (sprite._vertsDirty) {
            this.updateVerts(sprite);
            this.updateUVs(sprite);
            this.updateColor(sprite);
            this.update_indices(sprite);
            sprite._vertsDirty = false;
        }
    }

    update_indices(sprite: LightningSprite) {
        // let indices = data.iDatas[0];

        // indices[idx++] = vertextID + 0;
        // indices[idx++] = vertextID + 1;
        // indices[idx++] = vertextID + 2;
        // indices[idx++] = vertextID + 0;
        // indices[idx++] = vertextID + 2;
        // indices[idx++] = vertextID + 3;
        // indices[idx++] = vertextID + 0;
        // indices[idx++] = vertextID + 3;
        // indices[idx++] = vertextID + 4;
        // indices[idx++] = vertextID + 0;
        // indices[idx++] = vertextID + 4;
        // indices[idx++] = vertextID + 1;
    }

    // 将准备好的顶点数据填充进 VertexBuffer 和 IndiceBuffer
    fillBuffers(comp, renderer) {
        if (renderer.worldMatDirty) {
            this.updateWorldVerts(comp);
        }

        let renderData = this._renderData;
        let vData = renderData.vDatas[0];
        let iData = renderData.iDatas[0];

        let buffer = this.getBuffer(/*renderer*/);
        let offsetInfo = buffer.request(this.vertexesCount, this.indicesCount);

        // buffer data may be realloc, need get reference after request.

        // fill vertices
        let vertexOffset = offsetInfo.byteOffset >> 2,
            vbuf = buffer._vData;

        if (vData.length + vertexOffset > vbuf.length) {
            vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
        } else {
            vbuf.set(vData, vertexOffset);
        }

        // fill indices
        let ibuf = buffer._iData,
            indiceOffset = offsetInfo.indiceOffset,
            vertexId = offsetInfo.vertexOffset;             // vertexId是已经在buffer里的顶点数，也是当前顶点序号的基数
        for (let i = 0, l = iData.length; i < l; i++) {
            ibuf[indiceOffset++] = vertexId + iData[i];
        }
    }

    gen_lightning() {

    }

    updateVerts(sprite: cc.Sprite) {

        let node = sprite.node,
            cw = node.width, ch = node.height,
            appx = node.anchorX * cw, appy = node.anchorY * ch,
            l, b, r, t;

        let local = this._local;
        local[1] = cc.v2(-cw / 2, ch / 2);
        local[2] = cc.v2(cw / 2, ch / 2);
        local[3] = cc.v2(cw / 2, -ch / 2);
        local[4] = cc.v2(-cw / 2, -ch / 2);

        this.updateWorldVerts(sprite);

        // let verts = this._renderData.vDatas[0];
    }
    // updateVerts(sprite: cc.Sprite) {

    //     let node = sprite.node,
    //         cw = node.width, ch = node.height,
    //         appx = node.anchorX * cw, appy = node.anchorY * ch,
    //         l, b, r, t;

    //     let midPoint = this._anchorPoint;
    //     if (sprite.trim) {
    //         l = -appx;
    //         b = -appy;
    //         r = cw - appx;
    //         t = ch - appy;
    //     }
    //     else {
    //         let frame = sprite.spriteFrame,
    //             ow = frame.getOriginalSize().width, oh = frame.getOriginalSize().height,
    //             rw = frame.getRect().width, rh = frame.getRect().height,
    //             offset = frame.getOffset(),
    //             scaleX = cw / ow, scaleY = ch / oh;
    //         let trimLeft = offset.x + (ow - rw) / 2;
    //         let trimRight = offset.x - (ow - rw) / 2;
    //         let trimBottom = offset.y + (oh - rh) / 2;
    //         let trimTop = offset.y - (oh - rh) / 2;
    //         l = trimLeft * scaleX - appx;
    //         b = trimBottom * scaleY - appy;
    //         r = cw + trimRight * scaleX - appx;
    //         t = ch + trimTop * 1 - scaleY - appy;
    //     }

    //     let local = this._local;
    //     local[0] = l;
    //     local[1] = b;
    //     local[2] = r;
    //     local[3] = t;
    //     local[4] = midPoint;

    //     this.updateWorldVerts(sprite);

    //     // let verts = this._renderData.vDatas[0];
    // }

    /**
     * 1 2
     *  0
     * 4 3
     */

    updateUVs(sprite) {
        let uvs = sprite.spriteFrame.uv;
        let l = uvs[0],
            b = uvs[1],
            r = uvs[6],
            t = uvs[7],
            mx = l + (r - l) / 2,
            my = b + (t - b) / 2
            ;

        let uv = [mx, my, l, t, r, t, r, b, l, b];
        if (sprite.spriteFrame.isRotated()) {
            uv = [mx, my, r, b, r, t, l, t, l, b];
            // uv = [mx, my, l, b, l, t, r, t, r, b];
        }
        // let uv = [0.5, 0.5, 0, 1, 1, 1, 1, 0, 0, 0];
        let uvOffset = this.uvOffset;
        let floatsPerVert = this.floatsPerVert;
        let verts = this._renderData.vDatas[0];
        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中5个顶点的uv部分
        for (let i = 0; i < 4; i++) {
            let srcOffset = i * 2;
            let dstOffset = floatsPerVert * i + uvOffset;
            verts[dstOffset] = uv[srcOffset];
            verts[dstOffset + 1] = uv[srcOffset + 1];
        }
    }

    updateColor(comp, color = null) {
        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中4个顶点的color部分
        let uintVerts = this._renderData.uintVDatas[0];
        if (!uintVerts) return;
        color = color != null ? color : comp.node.color._val;
        let floatsPerVert = this.floatsPerVert;
        let colorOffset = this.colorOffset;
        for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) {
            uintVerts[i] = color;
        }
    }


    updateWorldVerts(comp) {
        if (CC_NATIVERENDERER) {
            this.updateWorldVertsNative(comp);
        } else {
            this.updateWorldVertsWebGL(comp);
        }
    }

    updateWorldVertsWebGL(comp) {
        let local = this._local;
        let verts = this._renderData.vDatas[0];
        let matrix = comp.node._worldMatrix;
        let matrixm = matrix.m,
            a = matrixm[0], b = matrixm[1], c = matrixm[4], d = matrixm[5],
            tx = matrixm[12], ty = matrixm[13];
        /*
        m00 = 1, m01 = 0, m02 = 0, m03 = 0,
        m04 = 0, m05 = 1, m06 = 0, m07 = 0,
        m08 = 0, m09 = 0, m10 = 1, m11 = 0,
        m12 = 0, m13 = 0, m14 = 0, m15 = 1
        */
        // [a,b,c,d] = _worldMatrix[1,2,4,5] == [1,0,0,1]
        // _worldMatrix[12,13]是xy的平移量
        // 即世界矩阵的左上角2x2是单元矩阵，说明在2D场景内没有出现旋转或者缩放
        let justTranslate = a === 1 && b === 0 && c === 0 && d === 1;

        // render data = verts = x|y|u|v|color|x|y|u|v|color|...
        // 填充render data中4个顶点的xy部分
        let index = 0;
        let floatsPerVert = this.floatsPerVert;
        // 4对xy分别乘以 [2,2]仿射矩阵，然后+平移量

        for (let i = 0; i < 5; i++) {
            let p = local[i];
            // mid
            // console.log('index', index, index + 1)
            verts[index] = p.x * a + p.y * c + tx;
            verts[index + 1] = p.x * b + p.y * d + ty;
            index += floatsPerVert;
        }
    }
    // updateWorldVertsWebGL(comp) {
    //     let local = this._local;
    //     let verts = this._renderData.vDatas[0];

    //     let matrix = comp.node._worldMatrix;
    //     let matrixm = matrix.m,
    //         a = matrixm[0], b = matrixm[1], c = matrixm[4], d = matrixm[5],
    //         tx = matrixm[12], ty = matrixm[13];

    //     let vl = local[0], vr = local[2],
    //         vb = local[1], vt = local[3],
    //         mid = local[4]
    //         ;

    //     /*
    //     m00 = 1, m01 = 0, m02 = 0, m03 = 0,
    //     m04 = 0, m05 = 1, m06 = 0, m07 = 0,
    //     m08 = 0, m09 = 0, m10 = 1, m11 = 0,
    //     m12 = 0, m13 = 0, m14 = 0, m15 = 1
    //     */
    //     // [a,b,c,d] = _worldMatrix[1,2,4,5] == [1,0,0,1]
    //     // _worldMatrix[12,13]是xy的平移量
    //     // 即世界矩阵的左上角2x2是单元矩阵，说明在2D场景内没有出现旋转或者缩放
    //     let justTranslate = a === 1 && b === 0 && c === 0 && d === 1;

    //     // render data = verts = x|y|u|v|color|x|y|u|v|color|...
    //     // 填充render data中4个顶点的xy部分
    //     let index = 0;
    //     let floatsPerVert = this.floatsPerVert;
    //     if (justTranslate && false) {
    //         // mid
    //         verts[index] = mid.x + tx;
    //         verts[index + 1] = mid.y + ty;
    //         index += floatsPerVert;
    //         // left top
    //         verts[index] = vl + tx;
    //         verts[index + 1] = vt + ty;
    //         index += floatsPerVert;
    //         // right top
    //         verts[index] = vr + tx;
    //         verts[index + 1] = vt + ty;
    //         index += floatsPerVert;
    //         // right bottom
    //         verts[index] = vr + tx;
    //         verts[index + 1] = vb + ty;
    //         index += floatsPerVert;
    //         // left bottom
    //         verts[index] = vl + tx;
    //         verts[index + 1] = vb + ty;
    //     } else {
    //         // 4对xy分别乘以 [2,2]仿射矩阵，然后+平移量
    //         let al = a * vl, ar = a * vr,
    //             bl = b * vl, br = b * vr,
    //             cb = c * vb, ct = c * vt,
    //             db = d * vb, dt = d * vt
    //             ;

    //         // mid
    //         verts[index] = mid.x + tx;
    //         verts[index + 1] = mid.y + ty;
    //         index += floatsPerVert;
    //         // newx = vl * a + vb * c + tx
    //         // newy = vl * b + vb * d + ty
    //         // left top
    //         verts[index] = al + ct + tx;
    //         verts[index + 1] = bl + dt + ty;
    //         index += floatsPerVert;
    //         // right top
    //         verts[index] = ar + ct + tx;
    //         verts[index + 1] = br + dt + ty;
    //         index += floatsPerVert;
    //         // right bottom
    //         verts[index] = ar + cb + tx;
    //         verts[index + 1] = br + db + ty;
    //         index += floatsPerVert;
    //         // left bottom
    //         verts[index] = al + cb + tx;
    //         verts[index + 1] = bl + db + ty;
    //     }
    // }

    // native场景下使用的updateWorldVerts
    // copy from \jsb-adapter-master\engine\assemblers\assembler-2d.js
    updateWorldVertsNative(comp) {
        let local = this._local;
        let verts = this._renderData.vDatas[0];
        let floatsPerVert = this.floatsPerVert;

        let vl = local[0],
            vr = local[2],
            vb = local[1],
            vt = local[3],
            mid = local[4]
            ;

        let index: number = 0;
        for (let i = 0; i < 5; i++) {
            let p = local[i];
            // mid
            console.log('index', index, index + 1)
            verts[index] = p.x;
            verts[index + 1] = p.y;
            index += floatsPerVert;
        }
    }
    // updateWorldVertsNative(comp) {
    //     let local = this._local;
    //     let verts = this._renderData.vDatas[0];
    //     let floatsPerVert = this.floatsPerVert;

    //     let vl = local[0],
    //         vr = local[2],
    //         vb = local[1],
    //         vt = local[3],
    //         mid = local[4]
    //         ;

    //     let index: number = 0;
    //     // mid
    //     verts[index] = mid.x;
    //     verts[index + 1] = mid.y;
    //     index += floatsPerVert;
    //     // left top
    //     verts[index] = vl;
    //     verts[index + 1] = vt;
    //     index += floatsPerVert;
    //     // right top
    //     verts[index] = vr;
    //     verts[index + 1] = vt;
    //     index += floatsPerVert;
    //     // right bottom
    //     verts[index] = vr;
    //     verts[index + 1] = vb;
    //     index += floatsPerVert;
    //     // left bottom
    //     verts[index] = vl;
    //     verts[index + 1] = vb;
    // }

    packToDynamicAtlas(comp, frame) {
        if (CC_TEST) return;

        if (!frame._original && cc.dynamicAtlasManager && frame._texture.packable) {
            let packedFrame = cc.dynamicAtlasManager.insertSpriteFrame(frame);
            //@ts-ignore
            if (packedFrame) {
                frame._setDynamicAtlasFrame(packedFrame);
            }
        }
        let material = comp._materials[0];
        if (!material) return;

        if (material.getProperty('texture') !== frame._texture) {
            // texture was packed to dynamic atlas, should update uvs
            comp._vertsDirty = true;
            comp._activateMaterial();
        }
    }
}

@ccclass
@executeInEditMode
@menu('i18n:MAIN_MENU.component.renderers/LightningSprite')
export default class LightningSprite extends cc.Sprite {

    meshRenderer: cc.MeshRenderer = null;

    _assembler: lightningAssembler = null;


    update_vertexes() {
        let assembler = this._assembler as lightningAssembler;
        if (!assembler) {
            return;
        }

        // assembler.gen_lightning(this.get_lightning_points());
        this.setVertsDirty();
    }

    _lightning_points: cc.Vec2[][] = [];
    get_lightning_points() {
        return this._lightning_points;
    }
    add_lightning_points(v: cc.Vec2[]) {
        this._lightning_points.push(v);
    }
    set_lightning_points(v: cc.Vec2[][]) {
        this._lightning_points = v;
        this.update_vertexes()
    }

    onEnable() {
        super.onEnable();
    }

    _resetAssembler() {
        this.setVertsDirty();
        let assembler = this._assembler = new lightningAssembler();
        this.update_vertexes();

        assembler.init(this);

        //@ts-ignore
        this._updateColor();
    }

    /*————————————————————————————————————————————*/

    onLoad() {

    }

    get_random_points(start: cc.Vec2, end: cc.Vec2): cc.Vec2[] {
        let points = [];
        return
    }

    gen_random_lightning_points() {
        this.add_lightning_points(this.get_random_points(cc.v2(), cc.v2(0, 260)));
        this.add_lightning_points(this.get_random_points(cc.v2(), cc.v2(200, -200)));
        this.add_lightning_points(this.get_random_points(cc.v2(), cc.v2(200, -200)));

        this.update_vertexes()
    }
}
